Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(deps): update all non-major dependencies #1418

Merged
merged 1 commit into from
Dec 18, 2024

Conversation

renovate[bot]
Copy link
Contributor

@renovate renovate bot commented Dec 18, 2024

This PR contains the following updates:

Package Change Age Adoption Passing Confidence Type Update Pending
@apollo/client (source) 3.12.2 -> 3.12.3 age adoption passing confidence dependencies patch
@emotion/react (source) 11.13.5 -> 11.14.0 age adoption passing confidence dependencies minor
@emotion/styled (source) 11.13.5 -> 11.14.0 age adoption passing confidence dependencies minor
@mui/icons-material (source) 6.1.10 -> 6.2.0 age adoption passing confidence dependencies minor 6.2.1
@mui/lab (source) 6.0.0-beta.18 -> 6.0.0-beta.19 age adoption passing confidence dependencies patch 6.0.0-beta.20
@mui/material (source) 6.1.10 -> 6.2.0 age adoption passing confidence dependencies minor 6.2.1
@mui/x-data-grid (source) 7.23.1 -> 7.23.2 age adoption passing confidence dependencies patch
@mui/x-date-pickers (source) 7.23.1 -> 7.23.2 age adoption passing confidence dependencies patch
@types/react (source) 18.3.14 -> 18.3.16 age adoption passing confidence devDependencies patch 18.3.17
@types/react-dom (source) 18.3.2 -> 18.3.5 age adoption passing confidence devDependencies patch
eslint-plugin-lingui 0.8.2 -> 0.8.3 age adoption passing confidence devDependencies patch 0.8.4
github/codeql-action v3.27.6 -> v3.27.9 age adoption passing confidence action patch
knip (source) 5.39.2 -> 5.40.0 age adoption passing confidence devDependencies minor 5.41.0
lint-staged 15.2.10 -> 15.2.11 age adoption passing confidence devDependencies patch
typescript-eslint (source) 8.17.0 -> 8.18.0 age adoption passing confidence devDependencies minor 8.18.1

Release Notes

apollographql/apollo-client (@​apollo/client)

v3.12.3

Compare Source

Patch Changes
emotion-js/emotion (@​emotion/react)

v11.14.0

Compare Source

Minor Changes
  • #​3284 a19d019 Thanks @​Andarist! - Source code has been migrated to TypeScript. From now on type declarations will be emitted based on that, instead of being hand-written.
Patch Changes
mui/material-ui (@​mui/icons-material)

v6.2.0

Compare Source

Dec 10, 2024

A big thanks to the 9 contributors who made this release possible. Here are some highlights ✨:

  • Material UI is now compatible with React 19 (#​44672) @​DiegoAndai
  • Fixed incorrect aria-orientation for vertical sliders. ArrowRight now increases the value and ArrowLeft decreases the value in vertical sliders; they were reversed in prior versions. (#​44537) @​mj12albert
@mui/[email protected]
Docs
Core

All contributors of this release in alphabetical order: @​aarongarciah, @​alexfauquette, @​bharatkashyap, @​DiegoAndai, @​Janpot, @​mj12albert, @​mnajdova, @​sai6855, @​SuperMaxine, @​vladmoroz, @​ZeeshanTamboli

mui/mui-x (@​mui/x-data-grid)

v7.23.2

Compare Source

Dec 12, 2024

We'd like to offer a big thanks to the 11 contributors who made this release possible. Here are some highlights ✨:

  • 🌍 Improve Romanian and Turkish locales on the Data Grid
  • 🌍 Improve Romanian locale on the Pickers
  • 📚 Documentation improvements
  • 🐞 Bugfixes

Special thanks go out to the community contributors who have helped make this release possible:
@​ihsanberkozcan, @​k-rajat19, @​lhilgert9, @​nusr, @​rares985.

Following are all team members who have contributed to this release:
@​alexfauquette, @​arminmeh, @​flaviendelangle, @​JCQuintas, @​KenanYusuf, @​LukasTy.

Data Grid
@mui/[email protected]
@mui/[email protected] pro

Same changes as in @mui/[email protected], plus:

@mui/[email protected] premium

Same changes as in @mui/[email protected], plus:

  • [DataGridPremium] Fix group column ignoring valueOptions for singleSelect column type (#​15754) @​arminmeh
Date and Time Pickers
@mui/[email protected]
@mui/[email protected] pro

Same changes as in @mui/[email protected].

Charts
@mui/[email protected]
@mui/[email protected] pro

Same changes as in @mui/[email protected].

@mui/[email protected]

No changes, releasing to keep the versions in sync.

@mui/[email protected] pro

Releasing to benefit from license package fix (#​15818).

Docs
Core
lingui/eslint-plugin (eslint-plugin-lingui)

v0.8.3

Compare Source

What's Changed

Full Changelog: lingui/eslint-plugin@0.8.2...0.8.3

github/codeql-action (github/codeql-action)

v3.27.9

Compare Source

CodeQL Action Changelog

See the releases page for the relevant changes to the CodeQL CLI and language packs.

Note that the only difference between v2 and v3 of the CodeQL Action is the node version they support, with v3 running on node 20 while we continue to release v2 to support running on node 16. For example 3.22.11 was the first v3 release and is functionally identical to 2.22.11. This approach ensures an easy way to track exactly which features are included in different versions, indicated by the minor and patch version numbers.

3.27.9 - 12 Dec 2024

No user facing changes.

See the full CHANGELOG.md for more information.

v3.27.8

Compare Source

v3.27.7

Compare Source

CodeQL Action Changelog

See the releases page for the relevant changes to the CodeQL CLI and language packs.

Note that the only difference between v2 and v3 of the CodeQL Action is the node version they support, with v3 running on node 20 while we continue to release v2 to support running on node 16. For example 3.22.11 was the first v3 release and is functionally identical to 2.22.11. This approach ensures an easy way to track exactly which features are included in different versions, indicated by the minor and patch version numbers.

3.27.7 - 10 Dec 2024
  • We are rolling out a change in December 2024 that will extract the CodeQL bundle directly to the toolcache to improve performance. #​2631
  • Update default CodeQL bundle version to 2.20.0. #​2636

See the full CHANGELOG.md for more information.

webpro-nl/knip (knip)

v5.40.0

Compare Source

v5.39.4

Compare Source

  • Ignore ignore patterns in vite test.include patterns (df390a0)
  • Stop using package.json as fallback containingFilePath (de6682b)

v5.39.3

Compare Source

  • Doc edits (0f640e1)
  • feat: update mdx detection dependency list and update custom compiler… (#​875) (055a2e3)
  • Add new content configuration entry for Astro (#​872) (c80ac0e)
lint-staged/lint-staged (lint-staged)

v15.2.11

Compare Source

Patch Changes
  • #​1484 bcfe309 Thanks @​wormsik! - Escape paths containing spaces when using the "shell" option.

  • #​1487 7dd8caa Thanks @​iiroj! - Do not treat submodule root paths as "staged files". This caused lint-staged to fail to a Git error when only updating the revision of a submodule.

typescript-eslint/typescript-eslint (typescript-eslint)

v8.18.0

Compare Source

🩹 Fixes
❤️ Thank You
  • rtritto

You can read about our versioning strategy and releases on our website.


Configuration

📅 Schedule: Branch creation - "* 0-4 * * 3" (UTC), Automerge - At any time (no schedule defined).

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

👻 Immortal: This PR will be recreated if closed unmerged. Get config help if that's undesired.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate renovate bot requested a review from tackley as a code owner December 18, 2024 01:26
@renovate renovate bot added the dependencies Pull requests that update a dependency file label Dec 18, 2024
Copy link

[puLL-Merge] - apollographql/[email protected]

Diff
diff --git .api-reports/api-report-cache.api.md .api-reports/api-report-cache.api.md
index 72f792334a2..908176a26cf 100644
--- .api-reports/api-report-cache.api.md
+++ .api-reports/api-report-cache.api.md
@@ -236,8 +236,12 @@ type CombineIntersection<T> = Exclude<T, {
     __typename?: string;
 }>>;
 
+// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts
+//
 // @public (undocumented)
-type ContainsFragmentsRefs<TData> = TData extends object ? " $fragmentRefs" extends keyof TData ? true : ContainsFragmentsRefs<TData[keyof TData]> : false;
+type ContainsFragmentsRefs<TData, Seen = never> = true extends (IsAny<TData>) ? false : TData extends object ? Exact<TData> extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature<TData> ? true : ContainsFragmentsRefs<TData[keyof TData], Seen | Exact<TData>> : false;
 
 // @public (undocumented)
 export function createFragmentRegistry(...fragments: DocumentNode[]): FragmentRegistryAPI;
@@ -462,6 +466,9 @@ export namespace EntityStore {
     }
 }
 
+// @public (undocumented)
+type Exact<in out T> = (x: T) => T;
+
 // @public
 type ExtractByMatchingTypeNames<Union extends {
     __typename?: string;
@@ -757,7 +764,6 @@ export function makeReference(id: string): Reference;
 // @public (undocumented)
 export function makeVar<T>(value: T): ReactiveVar<T>;
 
-// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "RemoveMaskedMarker" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "DataMasking" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "ContainsFragmentsRefs" needs to be exported by the entry point index.d.ts
@@ -1033,6 +1039,11 @@ export interface Reference {
 // @public (undocumented)
 type RemoveFragmentName<T> = T extends any ? Omit<T, " $fragmentName"> : T;
 
+// @public (undocumented)
+type RemoveIndexSignature<T> = {
+    [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K];
+};
+
 // @public (undocumented)
 type RemoveMaskedMarker<T> = Omit<T, "__masked">;
 
@@ -1109,7 +1120,7 @@ type Unmasked<TData> = true extends IsAny<TData> ? TData : TData extends object
 // @public (undocumented)
 type UnwrapFragmentRefs<TData> = true extends IsAny<TData> ? TData : TData extends any ? string extends keyof TData ? TData : keyof TData extends never ? TData : TData extends {
     " $fragmentRefs"?: infer FragmentRefs;
-} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends Array<infer TItem> ? Array<UnwrapFragmentRefs<TItem>> : TData extends object ? {
+} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends object ? {
     [K in keyof TData]: UnwrapFragmentRefs<TData[K]>;
 } : TData : never;
 
diff --git .api-reports/api-report-core.api.md .api-reports/api-report-core.api.md
index cb31ddd4692..81836428979 100644
--- .api-reports/api-report-core.api.md
+++ .api-reports/api-report-core.api.md
@@ -479,8 +479,12 @@ type ConcastSourcesIterable<T> = Iterable<Source<T>>;
 // @public (undocumented)
 export const concat: typeof ApolloLink.concat;
 
+// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts
+//
 // @public (undocumented)
-type ContainsFragmentsRefs<TData> = TData extends object ? " $fragmentRefs" extends keyof TData ? true : ContainsFragmentsRefs<TData[keyof TData]> : false;
+type ContainsFragmentsRefs<TData, Seen = never> = true extends (IsAny<TData>) ? false : TData extends object ? Exact<TData> extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature<TData> ? true : ContainsFragmentsRefs<TData[keyof TData], Seen | Exact<TData>> : false;
 
 // @public (undocumented)
 export const createHttpLink: (linkOptions?: HttpOptions) => ApolloLink;
@@ -787,6 +791,9 @@ namespace EntityStore {
 // @public
 export type ErrorPolicy = "none" | "ignore" | "all";
 
+// @public (undocumented)
+type Exact<in out T> = (x: T) => T;
+
 // @public (undocumented)
 export const execute: typeof ApolloLink.execute;
 
@@ -1401,7 +1408,6 @@ interface MaskOperationOptions<TData> {
 // @public (undocumented)
 type MaybeAsync<T> = T | PromiseLike<T>;
 
-// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "RemoveMaskedMarker" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "ContainsFragmentsRefs" needs to be exported by the entry point index.d.ts
 //
@@ -2170,6 +2176,11 @@ export type RefetchWritePolicy = "merge" | "overwrite";
 // @public (undocumented)
 type RemoveFragmentName<T> = T extends any ? Omit<T, " $fragmentName"> : T;
 
+// @public (undocumented)
+type RemoveIndexSignature<T> = {
+    [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K];
+};
+
 // @public (undocumented)
 type RemoveMaskedMarker<T> = Omit<T, "__masked">;
 
@@ -2406,7 +2417,7 @@ export type Unmasked<TData> = true extends IsAny<TData> ? TData : TData extends
 // @public (undocumented)
 type UnwrapFragmentRefs<TData> = true extends IsAny<TData> ? TData : TData extends any ? string extends keyof TData ? TData : keyof TData extends never ? TData : TData extends {
     " $fragmentRefs"?: infer FragmentRefs;
-} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends Array<infer TItem> ? Array<UnwrapFragmentRefs<TItem>> : TData extends object ? {
+} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends object ? {
     [K in keyof TData]: UnwrapFragmentRefs<TData[K]>;
 } : TData : never;
 
diff --git .api-reports/api-report-masking.api.md .api-reports/api-report-masking.api.md
index 0d22ad2fe1b..fffd2efb2e1 100644
--- .api-reports/api-report-masking.api.md
+++ .api-reports/api-report-masking.api.md
@@ -220,8 +220,12 @@ type CombineIntersection<T> = Exclude<T, {
     __typename?: string;
 }>>;
 
+// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts
+//
 // @public (undocumented)
-type ContainsFragmentsRefs<TData> = TData extends object ? " $fragmentRefs" extends keyof TData ? true : ContainsFragmentsRefs<TData[keyof TData]> : false;
+type ContainsFragmentsRefs<TData, Seen = never> = true extends (IsAny<TData>) ? false : TData extends object ? Exact<TData> extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature<TData> ? true : ContainsFragmentsRefs<TData[keyof TData], Seen | Exact<TData>> : false;
 
 // @public (undocumented)
 export interface DataMasking {
@@ -357,6 +361,9 @@ export const disableWarningsSlot: {
 // @public (undocumented)
 type DistributedRequiredExclude<T, U> = T extends any ? Required<T> extends Required<U> ? Required<U> extends Required<T> ? never : T : T : T;
 
+// @public (undocumented)
+type Exact<in out T> = (x: T) => T;
+
 // @public
 type ExtractByMatchingTypeNames<Union extends {
     __typename?: string;
@@ -429,7 +436,6 @@ export function maskFragment<TData = unknown>(data: TData, document: TypedDocume
 // @internal (undocumented)
 export function maskOperation<TData = unknown>(data: TData, document: DocumentNode | TypedDocumentNode<TData>, cache: ApolloCache<unknown>): TData;
 
-// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "RemoveMaskedMarker" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "ContainsFragmentsRefs" needs to be exported by the entry point index.d.ts
 //
@@ -558,6 +564,11 @@ interface Reference {
 // @public (undocumented)
 type RemoveFragmentName<T> = T extends any ? Omit<T, " $fragmentName"> : T;
 
+// @public (undocumented)
+type RemoveIndexSignature<T> = {
+    [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K];
+};
+
 // @public (undocumented)
 type RemoveMaskedMarker<T> = Omit<T, "__masked">;
 
@@ -608,7 +619,7 @@ export type Unmasked<TData> = true extends IsAny<TData> ? TData : TData extends
 // @public (undocumented)
 type UnwrapFragmentRefs<TData> = true extends IsAny<TData> ? TData : TData extends any ? string extends keyof TData ? TData : keyof TData extends never ? TData : TData extends {
     " $fragmentRefs"?: infer FragmentRefs;
-} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends Array<infer TItem> ? Array<UnwrapFragmentRefs<TItem>> : TData extends object ? {
+} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends object ? {
     [K in keyof TData]: UnwrapFragmentRefs<TData[K]>;
 } : TData : never;
 
diff --git .api-reports/api-report-react.api.md .api-reports/api-report-react.api.md
index 8373acf4521..16e002d9106 100644
--- .api-reports/api-report-react.api.md
+++ .api-reports/api-report-react.api.md
@@ -577,8 +577,12 @@ class Concast<T> extends Observable<T> {
 // @public (undocumented)
 type ConcastSourcesIterable<T> = Iterable<Source<T>>;
 
+// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts
+//
 // @public (undocumented)
-type ContainsFragmentsRefs<TData> = TData extends object ? " $fragmentRefs" extends keyof TData ? true : ContainsFragmentsRefs<TData[keyof TData]> : false;
+type ContainsFragmentsRefs<TData, Seen = never> = true extends (IsAny<TData>) ? false : TData extends object ? Exact<TData> extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature<TData> ? true : ContainsFragmentsRefs<TData[keyof TData], Seen | Exact<TData>> : false;
 
 // @public (undocumented)
 export interface Context extends Record<string, any> {
@@ -776,6 +780,9 @@ export { DocumentType_2 as DocumentType }
 // @public
 type ErrorPolicy = "none" | "ignore" | "all";
 
+// @public (undocumented)
+type Exact<in out T> = (x: T) => T;
+
 // Warning: (ae-forgotten-export) The symbol "ExecutionPatchResultBase" needs to be exported by the entry point index.d.ts
 //
 // @public (undocumented)
@@ -1146,7 +1153,6 @@ interface MaskOperationOptions<TData> {
 // @public (undocumented)
 type MaybeAsync<T> = T | PromiseLike<T>;
 
-// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "RemoveMaskedMarker" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "DataMasking" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "ContainsFragmentsRefs" needs to be exported by the entry point index.d.ts
@@ -1955,6 +1961,11 @@ type RefetchWritePolicy = "merge" | "overwrite";
 // @public (undocumented)
 type RemoveFragmentName<T> = T extends any ? Omit<T, " $fragmentName"> : T;
 
+// @public (undocumented)
+type RemoveIndexSignature<T> = {
+    [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K];
+};
+
 // @public (undocumented)
 type RemoveMaskedMarker<T> = Omit<T, "__masked">;
 
@@ -2202,7 +2213,7 @@ type Unmasked<TData> = true extends IsAny<TData> ? TData : TData extends object
 // @public (undocumented)
 type UnwrapFragmentRefs<TData> = true extends IsAny<TData> ? TData : TData extends any ? string extends keyof TData ? TData : keyof TData extends never ? TData : TData extends {
     " $fragmentRefs"?: infer FragmentRefs;
-} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends Array<infer TItem> ? Array<UnwrapFragmentRefs<TItem>> : TData extends object ? {
+} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends object ? {
     [K in keyof TData]: UnwrapFragmentRefs<TData[K]>;
 } : TData : never;
 
diff --git .api-reports/api-report-react_components.api.md .api-reports/api-report-react_components.api.md
index c9ea4d9100a..051470cb154 100644
--- .api-reports/api-report-react_components.api.md
+++ .api-reports/api-report-react_components.api.md
@@ -523,8 +523,12 @@ class Concast<T> extends Observable<T> {
 // @public (undocumented)
 type ConcastSourcesIterable<T> = Iterable<Source<T>>;
 
+// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts
+//
 // @public (undocumented)
-type ContainsFragmentsRefs<TData> = TData extends object ? " $fragmentRefs" extends keyof TData ? true : ContainsFragmentsRefs<TData[keyof TData]> : false;
+type ContainsFragmentsRefs<TData, Seen = never> = true extends (IsAny<TData>) ? false : TData extends object ? Exact<TData> extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature<TData> ? true : ContainsFragmentsRefs<TData[keyof TData], Seen | Exact<TData>> : false;
 
 // @public (undocumented)
 interface DataMasking {
@@ -708,6 +712,9 @@ interface DocumentTransformOptions {
 // @public
 type ErrorPolicy = "none" | "ignore" | "all";
 
+// @public (undocumented)
+type Exact<in out T> = (x: T) => T;
+
 // Warning: (ae-forgotten-export) The symbol "ExecutionPatchResultBase" needs to be exported by the entry point index.d.ts
 //
 // @public (undocumented)
@@ -1009,7 +1016,6 @@ interface MaskOperationOptions<TData> {
 // @public (undocumented)
 type MaybeAsync<T> = T | PromiseLike<T>;
 
-// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "RemoveMaskedMarker" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "DataMasking" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "ContainsFragmentsRefs" needs to be exported by the entry point index.d.ts
@@ -1737,6 +1743,11 @@ type RefetchWritePolicy = "merge" | "overwrite";
 // @public (undocumented)
 type RemoveFragmentName<T> = T extends any ? Omit<T, " $fragmentName"> : T;
 
+// @public (undocumented)
+type RemoveIndexSignature<T> = {
+    [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K];
+};
+
 // @public (undocumented)
 type RemoveMaskedMarker<T> = Omit<T, "__masked">;
 
@@ -1935,7 +1946,7 @@ type Unmasked<TData> = true extends IsAny<TData> ? TData : TData extends object
 // @public (undocumented)
 type UnwrapFragmentRefs<TData> = true extends IsAny<TData> ? TData : TData extends any ? string extends keyof TData ? TData : keyof TData extends never ? TData : TData extends {
     " $fragmentRefs"?: infer FragmentRefs;
-} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends Array<infer TItem> ? Array<UnwrapFragmentRefs<TItem>> : TData extends object ? {
+} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends object ? {
     [K in keyof TData]: UnwrapFragmentRefs<TData[K]>;
 } : TData : never;
 
diff --git .api-reports/api-report-react_context.api.md .api-reports/api-report-react_context.api.md
index c9d716e731e..703cfb4825d 100644
--- .api-reports/api-report-react_context.api.md
+++ .api-reports/api-report-react_context.api.md
@@ -517,8 +517,12 @@ class Concast<T> extends Observable<T> {
 // @public (undocumented)
 type ConcastSourcesIterable<T> = Iterable<Source<T>>;
 
+// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts
+//
 // @public (undocumented)
-type ContainsFragmentsRefs<TData> = TData extends object ? " $fragmentRefs" extends keyof TData ? true : ContainsFragmentsRefs<TData[keyof TData]> : false;
+type ContainsFragmentsRefs<TData, Seen = never> = true extends (IsAny<TData>) ? false : TData extends object ? Exact<TData> extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature<TData> ? true : ContainsFragmentsRefs<TData[keyof TData], Seen | Exact<TData>> : false;
 
 // @public (undocumented)
 interface DataMasking {
@@ -702,6 +706,9 @@ interface DocumentTransformOptions {
 // @public
 type ErrorPolicy = "none" | "ignore" | "all";
 
+// @public (undocumented)
+type Exact<in out T> = (x: T) => T;
+
 // Warning: (ae-forgotten-export) The symbol "ExecutionPatchResultBase" needs to be exported by the entry point index.d.ts
 //
 // @public (undocumented)
@@ -1006,7 +1013,6 @@ interface MaskOperationOptions<TData> {
 // @public (undocumented)
 type MaybeAsync<T> = T | PromiseLike<T>;
 
-// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "RemoveMaskedMarker" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "DataMasking" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "ContainsFragmentsRefs" needs to be exported by the entry point index.d.ts
@@ -1665,6 +1671,11 @@ type RefetchWritePolicy = "merge" | "overwrite";
 // @public (undocumented)
 type RemoveFragmentName<T> = T extends any ? Omit<T, " $fragmentName"> : T;
 
+// @public (undocumented)
+type RemoveIndexSignature<T> = {
+    [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K];
+};
+
 // @public (undocumented)
 type RemoveMaskedMarker<T> = Omit<T, "__masked">;
 
@@ -1855,7 +1866,7 @@ type Unmasked<TData> = true extends IsAny<TData> ? TData : TData extends object
 // @public (undocumented)
 type UnwrapFragmentRefs<TData> = true extends IsAny<TData> ? TData : TData extends any ? string extends keyof TData ? TData : keyof TData extends never ? TData : TData extends {
     " $fragmentRefs"?: infer FragmentRefs;
-} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends Array<infer TItem> ? Array<UnwrapFragmentRefs<TItem>> : TData extends object ? {
+} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends object ? {
     [K in keyof TData]: UnwrapFragmentRefs<TData[K]>;
 } : TData : never;
 
diff --git .api-reports/api-report-react_hoc.api.md .api-reports/api-report-react_hoc.api.md
index 7579701495f..3f867350519 100644
--- .api-reports/api-report-react_hoc.api.md
+++ .api-reports/api-report-react_hoc.api.md
@@ -506,8 +506,12 @@ class Concast<T> extends Observable<T> {
 // @public (undocumented)
 type ConcastSourcesIterable<T> = Iterable<Source<T>>;
 
+// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts
+//
 // @public (undocumented)
-type ContainsFragmentsRefs<TData> = TData extends object ? " $fragmentRefs" extends keyof TData ? true : ContainsFragmentsRefs<TData[keyof TData]> : false;
+type ContainsFragmentsRefs<TData, Seen = never> = true extends (IsAny<TData>) ? false : TData extends object ? Exact<TData> extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature<TData> ? true : ContainsFragmentsRefs<TData[keyof TData], Seen | Exact<TData>> : false;
 
 // @public (undocumented)
 interface DataMasking {
@@ -700,6 +704,9 @@ interface DocumentTransformOptions {
 // @public
 type ErrorPolicy = "none" | "ignore" | "all";
 
+// @public (undocumented)
+type Exact<in out T> = (x: T) => T;
+
 // Warning: (ae-forgotten-export) The symbol "ExecutionPatchResultBase" needs to be exported by the entry point index.d.ts
 //
 // @public (undocumented)
@@ -1013,7 +1020,6 @@ interface MaskOperationOptions<TData> {
 // @public (undocumented)
 type MaybeAsync<T> = T | PromiseLike<T>;
 
-// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "RemoveMaskedMarker" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "DataMasking" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "ContainsFragmentsRefs" needs to be exported by the entry point index.d.ts
@@ -1694,6 +1700,11 @@ type RefetchWritePolicy = "merge" | "overwrite";
 // @public (undocumented)
 type RemoveFragmentName<T> = T extends any ? Omit<T, " $fragmentName"> : T;
 
+// @public (undocumented)
+type RemoveIndexSignature<T> = {
+    [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K];
+};
+
 // @public (undocumented)
 type RemoveMaskedMarker<T> = Omit<T, "__masked">;
 
@@ -1859,7 +1870,7 @@ type Unmasked<TData> = true extends IsAny<TData> ? TData : TData extends object
 // @public (undocumented)
 type UnwrapFragmentRefs<TData> = true extends IsAny<TData> ? TData : TData extends any ? string extends keyof TData ? TData : keyof TData extends never ? TData : TData extends {
     " $fragmentRefs"?: infer FragmentRefs;
-} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends Array<infer TItem> ? Array<UnwrapFragmentRefs<TItem>> : TData extends object ? {
+} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends object ? {
     [K in keyof TData]: UnwrapFragmentRefs<TData[K]>;
 } : TData : never;
 
diff --git .api-reports/api-report-react_hooks.api.md .api-reports/api-report-react_hooks.api.md
index b639caed65d..b252b2a672f 100644
--- .api-reports/api-report-react_hooks.api.md
+++ .api-reports/api-report-react_hooks.api.md
@@ -546,8 +546,12 @@ class Concast<T> extends Observable<T> {
 // @public (undocumented)
 type ConcastSourcesIterable<T> = Iterable<Source<T>>;
 
+// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts
+//
 // @public (undocumented)
-type ContainsFragmentsRefs<TData> = TData extends object ? " $fragmentRefs" extends keyof TData ? true : ContainsFragmentsRefs<TData[keyof TData]> : false;
+type ContainsFragmentsRefs<TData, Seen = never> = true extends (IsAny<TData>) ? false : TData extends object ? Exact<TData> extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature<TData> ? true : ContainsFragmentsRefs<TData[keyof TData], Seen | Exact<TData>> : false;
 
 // @public (undocumented)
 interface DataMasking {
@@ -731,6 +735,9 @@ interface DocumentTransformOptions {
 // @public
 type ErrorPolicy = "none" | "ignore" | "all";
 
+// @public (undocumented)
+type Exact<in out T> = (x: T) => T;
+
 // Warning: (ae-forgotten-export) The symbol "ExecutionPatchResultBase" needs to be exported by the entry point index.d.ts
 //
 // @public (undocumented)
@@ -1095,7 +1102,6 @@ interface MaskOperationOptions<TData> {
 // @public (undocumented)
 type MaybeAsync<T> = T | PromiseLike<T>;
 
-// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "RemoveMaskedMarker" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "DataMasking" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "ContainsFragmentsRefs" needs to be exported by the entry point index.d.ts
@@ -1814,6 +1820,11 @@ type RefetchWritePolicy = "merge" | "overwrite";
 // @public (undocumented)
 type RemoveFragmentName<T> = T extends any ? Omit<T, " $fragmentName"> : T;
 
+// @public (undocumented)
+type RemoveIndexSignature<T> = {
+    [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K];
+};
+
 // @public (undocumented)
 type RemoveMaskedMarker<T> = Omit<T, "__masked">;
 
@@ -2025,7 +2036,7 @@ type Unmasked<TData> = true extends IsAny<TData> ? TData : TData extends object
 // @public (undocumented)
 type UnwrapFragmentRefs<TData> = true extends IsAny<TData> ? TData : TData extends any ? string extends keyof TData ? TData : keyof TData extends never ? TData : TData extends {
     " $fragmentRefs"?: infer FragmentRefs;
-} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends Array<infer TItem> ? Array<UnwrapFragmentRefs<TItem>> : TData extends object ? {
+} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends object ? {
     [K in keyof TData]: UnwrapFragmentRefs<TData[K]>;
 } : TData : never;
 
diff --git .api-reports/api-report-react_internal.api.md .api-reports/api-report-react_internal.api.md
index f5587b3de51..3e43a1dafbb 100644
--- .api-reports/api-report-react_internal.api.md
+++ .api-reports/api-report-react_internal.api.md
@@ -525,8 +525,12 @@ class Concast<T> extends Observable<T> {
 // @public (undocumented)
 type ConcastSourcesIterable<T> = Iterable<Source<T>>;
 
+// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts
+//
 // @public (undocumented)
-type ContainsFragmentsRefs<TData> = TData extends object ? " $fragmentRefs" extends keyof TData ? true : ContainsFragmentsRefs<TData[keyof TData]> : false;
+type ContainsFragmentsRefs<TData, Seen = never> = true extends (IsAny<TData>) ? false : TData extends object ? Exact<TData> extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature<TData> ? true : ContainsFragmentsRefs<TData[keyof TData], Seen | Exact<TData>> : false;
 
 // Warning: (ae-forgotten-export) The symbol "PreloadQueryFunction" needs to be exported by the entry point index.d.ts
 //
@@ -715,6 +719,9 @@ interface DocumentTransformOptions {
 // @public
 type ErrorPolicy = "none" | "ignore" | "all";
 
+// @public (undocumented)
+type Exact<in out T> = (x: T) => T;
+
 // Warning: (ae-forgotten-export) The symbol "ExecutionPatchResultBase" needs to be exported by the entry point index.d.ts
 //
 // @public (undocumented)
@@ -1105,7 +1112,6 @@ interface MaskOperationOptions<TData> {
 // @public (undocumented)
 type MaybeAsync<T> = T | PromiseLike<T>;
 
-// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "RemoveMaskedMarker" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "DataMasking" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "ContainsFragmentsRefs" needs to be exported by the entry point index.d.ts
@@ -1867,6 +1873,11 @@ interface RejectedPromise<TValue> extends Promise<TValue> {
 // @public (undocumented)
 type RemoveFragmentName<T> = T extends any ? Omit<T, " $fragmentName"> : T;
 
+// @public (undocumented)
+type RemoveIndexSignature<T> = {
+    [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K];
+};
+
 // @public (undocumented)
 type RemoveMaskedMarker<T> = Omit<T, "__masked">;
 
@@ -2077,7 +2088,7 @@ type Unmasked<TData> = true extends IsAny<TData> ? TData : TData extends object
 // @public (undocumented)
 type UnwrapFragmentRefs<TData> = true extends IsAny<TData> ? TData : TData extends any ? string extends keyof TData ? TData : keyof TData extends never ? TData : TData extends {
     " $fragmentRefs"?: infer FragmentRefs;
-} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends Array<infer TItem> ? Array<UnwrapFragmentRefs<TItem>> : TData extends object ? {
+} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends object ? {
     [K in keyof TData]: UnwrapFragmentRefs<TData[K]>;
 } : TData : never;
 
diff --git .api-reports/api-report-react_ssr.api.md .api-reports/api-report-react_ssr.api.md
index cb40f4d1f28..d0560e817dd 100644
--- .api-reports/api-report-react_ssr.api.md
+++ .api-reports/api-report-react_ssr.api.md
@@ -486,8 +486,12 @@ class Concast<T> extends Observable<T> {
 // @public (undocumented)
 type ConcastSourcesIterable<T> = Iterable<Source<T>>;
 
+// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts
+//
 // @public (undocumented)
-type ContainsFragmentsRefs<TData> = TData extends object ? " $fragmentRefs" extends keyof TData ? true : ContainsFragmentsRefs<TData[keyof TData]> : false;
+type ContainsFragmentsRefs<TData, Seen = never> = true extends (IsAny<TData>) ? false : TData extends object ? Exact<TData> extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature<TData> ? true : ContainsFragmentsRefs<TData[keyof TData], Seen | Exact<TData>> : false;
 
 // @public (undocumented)
 interface DataMasking {
@@ -671,6 +675,9 @@ interface DocumentTransformOptions {
 // @public
 type ErrorPolicy = "none" | "ignore" | "all";
 
+// @public (undocumented)
+type Exact<in out T> = (x: T) => T;
+
 // Warning: (ae-forgotten-export) The symbol "ExecutionPatchResultBase" needs to be exported by the entry point index.d.ts
 //
 // @public (undocumented)
@@ -991,7 +998,6 @@ interface MaskOperationOptions<TData> {
 // @public (undocumented)
 type MaybeAsync<T> = T | PromiseLike<T>;
 
-// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "RemoveMaskedMarker" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "DataMasking" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "ContainsFragmentsRefs" needs to be exported by the entry point index.d.ts
@@ -1650,6 +1656,11 @@ type RefetchWritePolicy = "merge" | "overwrite";
 // @public (undocumented)
 type RemoveFragmentName<T> = T extends any ? Omit<T, " $fragmentName"> : T;
 
+// @public (undocumented)
+type RemoveIndexSignature<T> = {
+    [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K];
+};
+
 // @public (undocumented)
 type RemoveMaskedMarker<T> = Omit<T, "__masked">;
 
@@ -1840,7 +1851,7 @@ type Unmasked<TData> = true extends IsAny<TData> ? TData : TData extends object
 // @public (undocumented)
 type UnwrapFragmentRefs<TData> = true extends IsAny<TData> ? TData : TData extends any ? string extends keyof TData ? TData : keyof TData extends never ? TData : TData extends {
     " $fragmentRefs"?: infer FragmentRefs;
-} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends Array<infer TItem> ? Array<UnwrapFragmentRefs<TItem>> : TData extends object ? {
+} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends object ? {
     [K in keyof TData]: UnwrapFragmentRefs<TData[K]>;
 } : TData : never;
 
diff --git .api-reports/api-report-testing.api.md .api-reports/api-report-testing.api.md
index 00f01de37dd..0c7b64d8eee 100644
--- .api-reports/api-report-testing.api.md
+++ .api-reports/api-report-testing.api.md
@@ -476,8 +476,12 @@ class Concast<T> extends Observable<T> {
 // @public (undocumented)
 type ConcastSourcesIterable<T> = Iterable<Source<T>>;
 
+// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts
+//
 // @public (undocumented)
-type ContainsFragmentsRefs<TData> = TData extends object ? " $fragmentRefs" extends keyof TData ? true : ContainsFragmentsRefs<TData[keyof TData]> : false;
+type ContainsFragmentsRefs<TData, Seen = never> = true extends (IsAny<TData>) ? false : TData extends object ? Exact<TData> extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature<TData> ? true : ContainsFragmentsRefs<TData[keyof TData], Seen | Exact<TData>> : false;
 
 // @internal (undocumented)
 type CovariantUnaryFunction<out Arg, out Ret> = {
@@ -672,6 +676,9 @@ interface DocumentTransformOptions {
 // @public
 type ErrorPolicy = "none" | "ignore" | "all";
 
+// @public (undocumented)
+type Exact<in out T> = (x: T) => T;
+
 // Warning: (ae-forgotten-export) The symbol "ExecutionPatchResultBase" needs to be exported by the entry point index.d.ts
 //
 // @public (undocumented)
@@ -980,7 +987,6 @@ interface MaskOperationOptions<TData> {
 // @public (undocumented)
 type MaybeAsync<T> = T | PromiseLike<T>;
 
-// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "RemoveMaskedMarker" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "DataMasking" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "ContainsFragmentsRefs" needs to be exported by the entry point index.d.ts
@@ -1715,6 +1721,11 @@ type RefetchWritePolicy = "merge" | "overwrite";
 // @public (undocumented)
 type RemoveFragmentName<T> = T extends any ? Omit<T, " $fragmentName"> : T;
 
+// @public (undocumented)
+type RemoveIndexSignature<T> = {
+    [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K];
+};
+
 // @public (undocumented)
 type RemoveMaskedMarker<T> = Omit<T, "__masked">;
 
@@ -1891,7 +1902,7 @@ type Unmasked<TData> = true extends IsAny<TData> ? TData : TData extends object
 // @public (undocumented)
 type UnwrapFragmentRefs<TData> = true extends IsAny<TData> ? TData : TData extends any ? string extends keyof TData ? TData : keyof TData extends never ? TData : TData extends {
     " $fragmentRefs"?: infer FragmentRefs;
-} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends Array<infer TItem> ? Array<UnwrapFragmentRefs<TItem>> : TData extends object ? {
+} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends object ? {
     [K in keyof TData]: UnwrapFragmentRefs<TData[K]>;
 } : TData : never;
 
diff --git .api-reports/api-report-testing_core.api.md .api-reports/api-report-testing_core.api.md
index 1606498c68a..d46a9f55d1f 100644
--- .api-reports/api-report-testing_core.api.md
+++ .api-reports/api-report-testing_core.api.md
@@ -475,8 +475,12 @@ class Concast<T> extends Observable<T> {
 // @public (undocumented)
 type ConcastSourcesIterable<T> = Iterable<Source<T>>;
 
+// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts
+//
 // @public (undocumented)
-type ContainsFragmentsRefs<TData> = TData extends object ? " $fragmentRefs" extends keyof TData ? true : ContainsFragmentsRefs<TData[keyof TData]> : false;
+type ContainsFragmentsRefs<TData, Seen = never> = true extends (IsAny<TData>) ? false : TData extends object ? Exact<TData> extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature<TData> ? true : ContainsFragmentsRefs<TData[keyof TData], Seen | Exact<TData>> : false;
 
 // @internal (undocumented)
 type CovariantUnaryFunction<out Arg, out Ret> = {
@@ -671,6 +675,9 @@ interface DocumentTransformOptions {
 // @public
 type ErrorPolicy = "none" | "ignore" | "all";
 
+// @public (undocumented)
+type Exact<in out T> = (x: T) => T;
+
 // Warning: (ae-forgotten-export) The symbol "ExecutionPatchResultBase" needs to be exported by the entry point index.d.ts
 //
 // @public (undocumented)
@@ -979,7 +986,6 @@ interface MaskOperationOptions<TData> {
 // @public (undocumented)
 type MaybeAsync<T> = T | PromiseLike<T>;
 
-// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "RemoveMaskedMarker" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "DataMasking" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "ContainsFragmentsRefs" needs to be exported by the entry point index.d.ts
@@ -1672,6 +1678,11 @@ type RefetchWritePolicy = "merge" | "overwrite";
 // @public (undocumented)
 type RemoveFragmentName<T> = T extends any ? Omit<T, " $fragmentName"> : T;
 
+// @public (undocumented)
+type RemoveIndexSignature<T> = {
+    [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K];
+};
+
 // @public (undocumented)
 type RemoveMaskedMarker<T> = Omit<T, "__masked">;
 
@@ -1848,7 +1859,7 @@ type Unmasked<TData> = true extends IsAny<TData> ? TData : TData extends object
 // @public (undocumented)
 type UnwrapFragmentRefs<TData> = true extends IsAny<TData> ? TData : TData extends any ? string extends keyof TData ? TData : keyof TData extends never ? TData : TData extends {
     " $fragmentRefs"?: infer FragmentRefs;
-} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends Array<infer TItem> ? Array<UnwrapFragmentRefs<TItem>> : TData extends object ? {
+} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends object ? {
     [K in keyof TData]: UnwrapFragmentRefs<TData[K]>;
 } : TData : never;
 
diff --git .api-reports/api-report-utilities.api.md .api-reports/api-report-utilities.api.md
index 76b0f621592..a09ee2ed138 100644
--- .api-reports/api-report-utilities.api.md
+++ .api-reports/api-report-utilities.api.md
@@ -606,8 +606,11 @@ export type ConcastSourcesIterable<T> = Iterable<Source<T>>;
 // @public (undocumented)
 export function concatPagination<T = Reference>(keyArgs?: KeyArgs): FieldPolicy<T[]>;
 
+// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts
+//
 // @public (undocumented)
-type ContainsFragmentsRefs<TData> = TData extends object ? " $fragmentRefs" extends keyof TData ? true : ContainsFragmentsRefs<TData[keyof TData]> : false;
+type ContainsFragmentsRefs<TData, Seen = never> = true extends (IsAny<TData>) ? false : TData extends object ? Exact<TData> extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature<TData> ? true : ContainsFragmentsRefs<TData[keyof TData], Seen | Exact<TData>> : false;
 
 // @public (undocumented)
 export function createFragmentMap(fragments?: FragmentDefinitionNode[]): FragmentMap;
@@ -979,6 +982,9 @@ namespace EntityStore {
 // @public
 type ErrorPolicy = "none" | "ignore" | "all";
 
+// @public (undocumented)
+type Exact<in out T> = (x: T) => T;
+
 // Warning: (ae-forgotten-export) The symbol "ExecutionPatchResultBase" needs to be exported by the entry point index.d.ts
 //
 // @public (undocumented)
@@ -1689,7 +1695,6 @@ type MaybeAsync<T> = T | PromiseLike<T>;
 // @public (undocumented)
 export function maybeDeepFreeze<T>(obj: T): T;
 
-// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "RemoveMaskedMarker" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "DataMasking" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "ContainsFragmentsRefs" needs to be exported by the entry point index.d.ts
@@ -2519,6 +2524,11 @@ export type RemoveFragmentSpreadConfig = RemoveNodeConfig<FragmentSpreadNode>;
 // @public (undocumented)
 export function removeFragmentSpreadFromDocument(config: RemoveFragmentSpreadConfig[], doc: DocumentNode): DocumentNode | null;
 
+// @public (undocumented)
+export type RemoveIndexSignature<T> = {
+    [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K];
+};
+
 // @public (undocumented)
 type RemoveMaskedMarker<T> = Omit<T, "__masked">;
 
@@ -2770,7 +2780,7 @@ type Unmasked<TData> = true extends IsAny<TData> ? TData : TData extends object
 // @public (undocumented)
 type UnwrapFragmentRefs<TData> = true extends IsAny<TData> ? TData : TData extends any ? string extends keyof TData ? TData : keyof TData extends never ? TData : TData extends {
     " $fragmentRefs"?: infer FragmentRefs;
-} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends Array<infer TItem> ? Array<UnwrapFragmentRefs<TItem>> : TData extends object ? {
+} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends object ? {
     [K in keyof TData]: UnwrapFragmentRefs<TData[K]>;
 } : TData : never;
 
diff --git .api-reports/api-report.api.md .api-reports/api-report.api.md
index 3a4bac0f7a6..850d6e603b9 100644
--- .api-reports/api-report.api.md
+++ .api-reports/api-report.api.md
@@ -576,8 +576,12 @@ type ConcastSourcesIterable<T> = Iterable<Source<T>>;
 // @public (undocumented)
 export const concat: typeof ApolloLink.concat;
 
+// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "Exact" needs to be exported by the entry point index.d.ts
+// Warning: (ae-forgotten-export) The symbol "RemoveIndexSignature" needs to be exported by the entry point index.d.ts
+//
 // @public (undocumented)
-type ContainsFragmentsRefs<TData> = TData extends object ? " $fragmentRefs" extends keyof TData ? true : ContainsFragmentsRefs<TData[keyof TData]> : false;
+type ContainsFragmentsRefs<TData, Seen = never> = true extends (IsAny<TData>) ? false : TData extends object ? Exact<TData> extends Seen ? false : " $fragmentRefs" extends keyof RemoveIndexSignature<TData> ? true : ContainsFragmentsRefs<TData[keyof TData], Seen | Exact<TData>> : false;
 
 // @public (undocumented)
 export const createHttpLink: (linkOptions?: HttpOptions) => ApolloLink;
@@ -900,6 +904,9 @@ namespace EntityStore {
 // @public
 export type ErrorPolicy = "none" | "ignore" | "all";
 
+// @public (undocumented)
+type Exact<in out T> = (x: T) => T;
+
 // @public (undocumented)
 export const execute: typeof ApolloLink.execute;
 
@@ -1582,7 +1589,6 @@ interface MaskOperationOptions<TData> {
 // @public (undocumented)
 type MaybeAsync<T> = T | PromiseLike<T>;
 
-// Warning: (ae-forgotten-export) The symbol "IsAny" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "RemoveMaskedMarker" needs to be exported by the entry point index.d.ts
 // Warning: (ae-forgotten-export) The symbol "ContainsFragmentsRefs" needs to be exported by the entry point index.d.ts
 //
@@ -2552,6 +2558,11 @@ export type RefetchWritePolicy = "merge" | "overwrite";
 // @public (undocumented)
 type RemoveFragmentName<T> = T extends any ? Omit<T, " $fragmentName"> : T;
 
+// @public (undocumented)
+type RemoveIndexSignature<T> = {
+    [K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K];
+};
+
 // @public (undocumented)
 type RemoveMaskedMarker<T> = Omit<T, "__masked">;
 
@@ -2871,7 +2882,7 @@ export type Unmasked<TData> = true extends IsAny<TData> ? TData : TData extends
 // @public (undocumented)
 type UnwrapFragmentRefs<TData> = true extends IsAny<TData> ? TData : TData extends any ? string extends keyof TData ? TData : keyof TData extends never ? TData : TData extends {
     " $fragmentRefs"?: infer FragmentRefs;
-} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends Array<infer TItem> ? Array<UnwrapFragmentRefs<TItem>> : TData extends object ? {
+} ? UnwrapFragmentRefs<CombineIntersection<Omit<TData, " $fragmentRefs"> | RemoveFragmentName<NonNullable<NonNullable<FragmentRefs>[keyof NonNullable<FragmentRefs>]>>>> : TData extends object ? {
     [K in keyof TData]: UnwrapFragmentRefs<TData[K]>;
 } : TData : never;
 
diff --git .semgrepignore .semgrepignore
index 3031b723ab1..5b3c586139a 100644
--- .semgrepignore
+++ .semgrepignore
@@ -11,3 +11,4 @@ dist/
 # custom paths
 __tests__/
 ./docs/source/data/subscriptions.mdx
+./docs/source/development-testing/developer-tooling.mdx
\ No newline at end of file
diff --git .size-limits.json .size-limits.json
index 54bce409ebd..c7b4947027f 100644
--- .size-limits.json
+++ .size-limits.json
@@ -1,4 +1,4 @@
 {
-  "dist/apollo-client.min.cjs": 41613,
+  "dist/apollo-client.min.cjs": 41615,
   "import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 34349
 }
diff --git CHANGELOG.md CHANGELOG.md
index 173e739fd1e..76411547510 100644
--- CHANGELOG.md
+++ CHANGELOG.md
@@ -1,5 +1,17 @@
 # @apollo/client
 
+## 3.12.3
+
+### Patch Changes
+
+- [#12214](https://github.com/apollographql/apollo-client/pull/12214) [`8bfee88`](https://github.com/apollographql/apollo-client/commit/8bfee88102dd071ea5836f7267f30ca082671b2b) Thanks [@phryneas](https://github.com/phryneas)! - Data masking: prevent infinite recursion of `ContainsFragmentsRefs` type
+
+- [#12204](https://github.com/apollographql/apollo-client/pull/12204) [`851deb0`](https://github.com/apollographql/apollo-client/commit/851deb06f42eb255b4839c2b88430f991943ae0f) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Fix `Unmasked` unwrapping tuple types into an array of their subtypes.
+
+- [#12204](https://github.com/apollographql/apollo-client/pull/12204) [`851deb0`](https://github.com/apollographql/apollo-client/commit/851deb06f42eb255b4839c2b88430f991943ae0f) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Ensure `MaybeMasked` does not try and unwrap types that contain index signatures.
+
+- [#12204](https://github.com/apollographql/apollo-client/pull/12204) [`851deb0`](https://github.com/apollographql/apollo-client/commit/851deb06f42eb255b4839c2b88430f991943ae0f) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Ensure `MaybeMasked` does not try to unwrap the type as `Unmasked` if the type contains `any`.
+
 ## 3.12.2
 
 ### Patch Changes
diff --git ROADMAP.md ROADMAP.md
index 9840dd9dfd1..2d96bae7d14 100644
--- ROADMAP.md
+++ ROADMAP.md
@@ -1,6 +1,6 @@
 # 🔮 Apollo Client Ecosystem Roadmap
 
-**Last updated: 2024-11-04**
+**Last updated: 2024-12-11**
 
 For up to date release notes, refer to the project's [Changelog](https://github.com/apollographql/apollo-client/blob/main/CHANGELOG.md).
 
@@ -17,42 +17,41 @@ For up to date release notes, refer to the project's [Changelog](https://github.
 
 ### Apollo Client
 
-#### [3.12.0](https://github.com/apollographql/apollo-client/milestone/42) - November 18, 2024
-_Release candidate - November 11, 2024_
+#### [3.13.0](https://github.com/apollographql/apollo-client/milestone/42) - January 13, 2024
+_Release candidate - January 7th_
 
-- Data masking
+- `useSuspenseFragment`
 
 #### Upcoming features
 
-- Leaner client (under alternate entry point)
-- Better types for `useQuery`/`useMutation`/`useSubscription`
-- Introduce `useSuspenseFragment` that will suspend when the data is not yet loaded (experimental)
+- Deprecations and preparations for 4.0
 
 #### 4.0
 
-- `Release 4.0` will be our next major release of the Client and is still in early planning.  See Github [4.0 Milestone](https://github.com/apollographql/apollo-client/milestone/31) for more details.
+- `Release 4.0` will be our next major release of the Client and is still in planning. See Github [4.0 Milestone](https://github.com/apollographql/apollo-client/milestone/31) for more details.
 
 ### GraphQL Testing Library
 
 - New documentation
 - Subscription support (waiting for MSW WebSocket support to land)
 
+_These changes will take longer than anticipated due to prioritization on Apollo Client 4.0_
+
 ### VSCode Extension
 
-- Bug fixes and long-requested features
-- Apollo Client Devtools integration
+_No outstanding work_
 
 ### GraphQL Tag
 
-- Started 3.0 milestone planning
+- `Release 3.0` will be our next major release of `graphql-tag` and is still in planning. See Github [3.0 Milestone](https://github.com/apollographql/graphql-tag/milestone/3) for more details.
 
 ### Apollo Client DevTools
 
-- Ongoing work with fixing error messages shown in devtools
-- Add a memory panel to monitor Apollo Client devtools internal caches
-- Connectors debugger
+_These changes will take longer than anticipated due to prioritization on Apollo Client 4.0_
 
-### Apollo Client NextJS
+### Apollo Client React Framework Integrations
 
 - New/more robust documentation
 - Support for `@defer` in RSC
+- Support for Apollo Client Streaming in TanStack Router
+- Support for Apollo Client Streaming in React Router 7
diff --git config/jest.config.js config/jest.config.js
index ce297ed2af0..977c2e8e80a 100644
--- config/jest.config.js
+++ config/jest.config.js
@@ -63,17 +63,17 @@ const standardReact19Config = {
   ...defaults,
   displayName: "ReactDOM 19",
   testPathIgnorePatterns: react19TestFileIgnoreList,
-  moduleNameMapper: {
-    "^react$": "react-19",
-    "^react-dom$": "react-dom-19",
-    "^react-dom/(.*)$": "react-dom-19/$1",
-  },
 };
 
 const standardReact18Config = {
   ...defaults,
   displayName: "ReactDOM 18",
   testPathIgnorePatterns: [ignoreTSFiles],
+  moduleNameMapper: {
+    "^react$": "react-18",
+    "^react-dom$": "react-dom-18",
+    "^react-dom/(.*)$": "react-dom-18/$1",
+  },
 };
 
 const standardReact17Config = {
@@ -83,6 +83,7 @@ const standardReact17Config = {
   moduleNameMapper: {
     "^react$": "react-17",
     "^react-dom$": "react-dom-17",
+    "^react-dom/client$": "<rootDir>/../config/jest/react-dom-17-client.js",
     "^react-dom/server$": "react-dom-17/server",
     "^react-dom/test-utils$": "react-dom-17/test-utils",
   },
diff --git a/config/jest/react-dom-17-client.js b/config/jest/react-dom-17-client.js
new file mode 100644
index 00000000000..44a9ae85835
--- /dev/null
+++ config/jest/react-dom-17-client.js
@@ -0,0 +1,15 @@
+// Shim for React 17 react-dom/client entrypoint imported by React Testing
+// Library
+
+module.exports = {
+  hydrateRoot: () => {
+    throw new Error(
+      "Cannot use hydrateRoot with React 17. Ensure this uses legacy root instead"
+    );
+  },
+  createRoot: () => {
+    throw new Error(
+      "Cannot use createRoot with React 17. Ensure this uses legacy root instead"
+    );
+  },
+};
diff --git a/docs/source/assets/devtools/vscode-panel.png b/docs/source/assets/devtools/vscode-panel.png
new file mode 100644
index 00000000000..d330d1e74a3
Binary files /dev/null and b/docs/source/assets/devtools/vscode-panel.png differ
diff --git a/docs/source/assets/devtools/vscode-setting.png b/docs/source/assets/devtools/vscode-setting.png
new file mode 100644
index 00000000000..1d2db0fc272
Binary files /dev/null and b/docs/source/assets/devtools/vscode-setting.png differ
diff --git package.json package.json
index f84c9d53476..1e58fef8c9b 100644
--- package.json
+++ package.json
@@ -1,6 +1,6 @@
 {
   "name": "@apollo/client",
-  "version": "3.12.2",
+  "version": "3.12.3",
   "description": "A fully-featured caching GraphQL client.",
   "private": true,
   "keywords": [
@@ -122,9 +122,9 @@
     "@size-limit/esbuild-why": "11.1.4",
     "@size-limit/preset-small-lib": "11.1.4",
     "@testing-library/dom": "^10.4.0",
-    "@testing-library/jest-dom": "6.4.6",
-    "@testing-library/react": "^16.0.1",
-    "@testing-library/react-render-stream": "2.0.0-alpha.1",
+    "@testing-library/jest-dom": "6.6.3",
+    "@testing-library/react": "^16.1.0",
+    "@testing-library/react-render-stream": "2.0.0",
     "@testing-library/user-event": "14.5.2",
     "@tsconfig/node20": "20.1.4",
     "@types/bytes": "3.1.4",
@@ -135,8 +135,9 @@
     "@types/lodash": "4.17.7",
     "@types/node": "20.16.1",
     "@types/node-fetch": "2.6.11",
-    "@types/react": "18.3.3",
-    "@types/react-dom": "18.3.0",
+    "@types/prop-types": "^15.7.14",
+    "@types/react": "19.0.0",
+    "@types/react-dom": "19.0.0",
     "@types/relay-runtime": "14.1.24",
     "@types/use-sync-external-store": "0.0.6",
     "@typescript-eslint/eslint-plugin": "7.18.0",
@@ -168,12 +169,12 @@
     "patch-package": "8.0.0",
     "pkg-pr-new": "0.0.24",
     "prettier": "3.1.1",
-    "react": "18.3.1",
+    "react": "19.0.0",
     "react-17": "npm:react@^17",
-    "react-19": "npm:[email protected]",
-    "react-dom": "18.3.1",
+    "react-18": "npm:react@^18",
+    "react-dom": "19.0.0",
     "react-dom-17": "npm:react-dom@^17",
-    "react-dom-19": "npm:[email protected]",
+    "react-dom-18": "npm:react-dom@^18",
     "react-error-boundary": "4.0.13",
     "recast": "0.23.9",
     "resolve": "1.22.8",
diff --git a/patches/@testing-library+react+16.0.1.patch b/patches/@testing-library+react+16.1.0.patch
similarity index 100%
rename from patches/@testing-library+react+16.0.1.patch
rename to patches/@testing-library+react+16.1.0.patch
diff --git a/src/masking/__benches__/types.bench.ts b/src/masking/__benches__/types.bench.ts
diff --git src/masking/__benches__/types.bench.ts src/masking/__benches__/types.bench.ts
index 621fb29dfaf..0ae97b7edc4 100644
--- src/masking/__benches__/types.bench.ts
+++ src/masking/__benches__/types.bench.ts
@@ -299,7 +299,7 @@ test("MaybeMasked handles odd types", (prefix) => {
 
   bench(prefix + "unknown instantiations", () => {
     attest<unknown, MaybeMasked<unknown>>();
-  }).types([52, "instantiations"]);
+  }).types([54, "instantiations"]);
   bench(prefix + "unknown functionality", () => {
     expectTypeOf<MaybeMasked<unknown>>().toBeUnknown();
   });
@@ -464,3 +464,131 @@ test("base type, multiple fragments on sub-types", (prefix) => {
     }>();
   });
 });
+
+test("does not detect `$fragmentRefs` if type contains `any`", (prefix) => {
+  interface Source {
+    foo: { bar: any[] };
+    " $fragmentName": "foo";
+  }
+
+  bench(prefix + "instantiations", () => {
+    return {} as MaybeMasked<Source>;
+  }).types([6, "instantiations"]);
+
+  bench(prefix + "functionality", () => {
+    const x = {} as MaybeMasked<Source>;
+
+    expectTypeOf(x).branded.toEqualTypeOf<Source>();
+  });
+});
+
+test("leaves tuples alone", (prefix) => {
+  interface Source {
+    coords: [long: number, lat: number];
+  }
+
+  bench(prefix + "instantiations", () => {
+    return {} as Unmasked<Source>;
+  }).types([5, "instantiations"]);
+
+  bench(prefix + "functionality", () => {
+    const x = {} as Unmasked<Source>;
+
+    expectTypeOf(x).branded.toEqualTypeOf<{
+      coords: [long: number, lat: number];
+    }>();
+  });
+});
+
+test("does not detect `$fragmentRefs` if type is a record type", (prefix) => {
+  interface MetadataItem {
+    foo: string;
+  }
+
+  interface Source {
+    metadata: Record<string, MetadataItem>;
+    " $fragmentName": "Source";
+  }
+
+  bench(prefix + "instantiations", () => {
+    return {} as MaybeMasked<Source>;
+  }).types([6, "instantiations"]);
+
+  bench(prefix + "functionality", () => {
+    const x = {} as MaybeMasked<Source>;
+
+    expectTypeOf(x).branded.toEqualTypeOf<Source>();
+  });
+});
+
+test("does not detect `$fragmentRefs` on types with index signatures", (prefix) => {
+  interface Source {
+    foo: string;
+    " $fragmentName": "Source";
+    [key: string]: string;
+  }
+
+  bench(prefix + "instantiations", () => {
+    return {} as MaybeMasked<Source>;
+  }).types([6, "instantiations"]);
+
+  bench(prefix + "functionality", () => {
+    const x = {} as MaybeMasked<Source>;
+
+    expectTypeOf(x).branded.toEqualTypeOf<Source>();
+  });
+});
+
+test("detects `$fragmentRefs` on types with index signatures", (prefix) => {
+  type Source = {
+    __typename: "Foo";
+    id: number;
+    metadata: Record<string, number>;
+    structuredMetadata: StructuredMetadata;
+  } & { " $fragmentName"?: "UserFieldsFragment" } & {
+    " $fragmentRefs"?: {
+      FooFragment: FooFragment;
+    };
+  };
+
+  interface StructuredMetadata {
+    bar: number;
+    [index: string]: number;
+  }
+
+  type FooFragment = {
+    __typename: "Foo";
+    foo: string;
+  } & { " $fragmentName"?: "FooFragment" };
+
+  bench(prefix + "instantiations", () => {
+    return {} as MaybeMasked<Source>;
+  }).types([6, "instantiations"]);
+
+  bench(prefix + "functionality", () => {
+    const x = {} as MaybeMasked<Source>;
+
+    expectTypeOf(x).branded.toEqualTypeOf<{
+      __typename: "Foo";
+      id: number;
+      metadata: Record<string, number>;
+      foo: string;
+      structuredMetadata: StructuredMetadata;
+    }>();
+  });
+});
+
+test("recursive types: no error 'Type instantiation is excessively deep and possibly infinite.'", (prefix) => {
+  // this type is self-recursive
+  type Source = import("graphql").IntrospectionQuery;
+
+  bench(prefix + "instantiations", () => {
+    return {} as MaybeMasked<Source>;
+  }).types([6, "instantiations"]);
+
+  bench(prefix + "functionality", () => {
+    const x = {} as MaybeMasked<Source>;
+
+    expectTypeOf(x).branded.toEqualTypeOf<Source>();
+  });
+});
diff --git src/masking/internal/types.ts src/masking/internal/types.ts
index ead6b64abdf..828734a8934 100644
--- src/masking/internal/types.ts
+++ src/masking/internal/types.ts
@@ -1,4 +1,4 @@
-import type { Prettify } from "../../utilities/index.js";
+import type { Prettify, RemoveIndexSignature } from "../../utilities/index.js";
 
 export type IsAny<T> = 0 extends 1 & T ? true : false;
 
@@ -20,7 +20,6 @@ export type UnwrapFragmentRefs<TData> =
             >
         >
       >
-    : TData extends Array<infer TItem> ? Array<UnwrapFragmentRefs<TItem>>
     : TData extends object ?
       {
         [K in keyof TData]: UnwrapFragmentRefs<TData[K]>;
@@ -183,9 +182,13 @@ export type RemoveMaskedMarker<T> = Omit<T, "__masked">;
 export type RemoveFragmentName<T> =
   T extends any ? Omit<T, " $fragmentName"> : T;
 
-export type ContainsFragmentsRefs<TData> =
-  TData extends object ?
-    " $fragmentRefs" extends keyof TData ?
-      true
-    : ContainsFragmentsRefs<TData[keyof TData]>
-  : false;
+type Exact<in out T> = (x: T) => T;
+export type ContainsFragmentsRefs<TData, Seen = never> = true extends (
+  IsAny<TData>
+) ?
+  false
+: TData extends object ?
+  Exact<TData> extends Seen ? false
+  : " $fragmentRefs" extends keyof RemoveIndexSignature<TData> ? true
+  : ContainsFragmentsRefs<TData[keyof TData], Seen | Exact<TData>>
+: false;
diff --git src/react/components/__tests__/client/Query.test.tsx src/react/components/__tests__/client/Query.test.tsx
index a97807838aa..624d38f137d 100644
--- src/react/components/__tests__/client/Query.test.tsx
+++ src/react/components/__tests__/client/Query.test.tsx
@@ -210,7 +210,7 @@ describe("Query component", () => {
       ];
 
       const Component = () => (
-        <Query query={allPeopleQuery} data-ref={React.useRef()}>
+        <Query query={allPeopleQuery} data-ref={React.useRef(void 0)}>
           {(result: any) => {
             if (result.loading) {
               return null;
diff --git src/react/components/__tests__/ssr/getDataFromTree.test.tsx src/react/components/__tests__/ssr/getDataFromTree.test.tsx
index 6441008606e..326bdc6828c 100644
--- src/react/components/__tests__/ssr/getDataFromTree.test.tsx
+++ src/react/components/__tests__/ssr/getDataFromTree.test.tsx
@@ -3,7 +3,7 @@ import React from "react";
 import gql from "graphql-tag";
 import { DocumentNode } from "graphql";
 
-import { ApolloClient } from "../../../../core";
+import { ApolloClient, TypedDocumentNode } from "../../../../core";
 import { InMemoryCache as Cache } from "../../../../cache";
 import {
   ApolloProvider,
@@ -37,7 +37,7 @@ describe("SSR", () => {
     });
 
     it("should run through all of the queries (also defined via Query component) that want SSR", () => {
-      const query = gql`
+      const query: TypedDocumentNode<Data> = gql`
         {
           currentUser {
             firstName
@@ -63,7 +63,7 @@ describe("SSR", () => {
 
       const WrappedElement = () => (
         <Query query={query}>
-          {({ data, loading }: { data: Data; loading: boolean }) => (
+          {({ data, loading }) => (
             <div>
               {loading || !data ? "loading" : data.currentUser!.firstName}
             </div>
diff --git src/react/hoc/__tests__/queries/recomposeWithState.ts src/react/hoc/__tests__/queries/recomposeWithState.tsx
similarity index 87%
rename from src/react/hoc/__tests__/queries/recomposeWithState.ts
rename to src/react/hoc/__tests__/queries/recomposeWithState.tsx
index 2ec2ad79756..68535b077c3 100644
--- src/react/hoc/__tests__/queries/recomposeWithState.ts
+++ src/react/hoc/__tests__/queries/recomposeWithState.tsx
@@ -1,7 +1,7 @@
 // Adapted from v0.30.0 of https://github.com/acdlite/recompose/blob/master/src/packages/recompose/withState.js
 // to avoid incurring an indirect dependency on ua-parser-js via fb,js.
 
-import React, { createFactory, Component } from "react";
+import React, { Component } from "react";
 
 const setStatic =
   (key: string, value: string) => (BaseComponent: React.ComponentClass) => {
@@ -33,7 +33,6 @@ const wrapDisplayName = (
 export const withState =
   (stateName: string, stateUpdaterName: string, initialState: unknown) =>
   (BaseComponent: React.ComponentClass) => {
-    const factory = createFactory(BaseComponent);
     class WithState extends Component<
       Record<string, unknown>,
       { stateValue: unknown }
@@ -58,11 +57,15 @@ export const withState =
         );
 
       render() {
-        return factory({
-          ...this.props,
-          [stateName]: this.state.stateValue,
-          [stateUpdaterName]: this.updateStateValue,
-        });
+        return (
+          <BaseComponent
+            {...{
+              ...this.props,
+              [stateName]: this.state.stateValue,
+              [stateUpdaterName]: this.updateStateValue,
+            }}
+          />
+        );
       }
     }
 
diff --git src/react/hoc/__tests__/ssr/getDataFromTree.test.tsx src/react/hoc/__tests__/ssr/getDataFromTree.test.tsx
index 0a687741f64..70daf897951 100644
--- src/react/hoc/__tests__/ssr/getDataFromTree.test.tsx
+++ src/react/hoc/__tests__/ssr/getDataFromTree.test.tsx
@@ -5,7 +5,7 @@ import ReactDOM from "react-dom/server";
 import gql from "graphql-tag";
 import { DocumentNode } from "graphql";
 
-import { ApolloClient } from "../../../../core";
+import { ApolloClient, TypedDocumentNode } from "../../../../core";
 import { ApolloProvider } from "../../../context";
 import { InMemoryCache as Cache } from "../../../../cache";
 import { itAsync, mockSingleLink } from "../../../../testing";
@@ -805,7 +805,7 @@ describe("SSR", () => {
     });
 
     it("shouldn't run queries (via Query component) if ssr is turned to off", () => {
-      const query = gql`
+      const query: TypedDocumentNode<Data> = gql`
         query user($id: ID) {
           currentUser(id: $id) {
             firstName
@@ -833,7 +833,7 @@ describe("SSR", () => {
 
       const Element = (props: { id: string }) => (
         <Query query={query} ssr={false} variables={props}>
-          {({ data, loading }: { data: Data; loading: boolean }) => (
+          {({ data, loading }) => (
             <div>
               {loading || !data ? "loading" : data.currentUser!.firstName}
             </div>
diff --git src/react/hoc/mutation-hoc.tsx src/react/hoc/mutation-hoc.tsx
index 2a0291653d1..a9dc10e673f 100644
--- src/react/hoc/mutation-hoc.tsx
+++ src/react/hoc/mutation-hoc.tsx
@@ -5,11 +5,7 @@ import hoistNonReactStatics from "hoist-non-react-statics";
 
 import { parser } from "../parser/index.js";
 import type { DefaultContext, OperationVariables } from "../../core/types.js";
-import type {
-  BaseMutationOptions,
-  MutationFunction,
-  MutationResult,
-} from "../types/types.js";
+import type { BaseMutationOptions } from "../types/types.js";
 import { Mutation } from "../components/index.js";
 
 import {
@@ -91,12 +87,9 @@ export function withMutation<
         }
 
         return (
+          // @ts-expect-error
           <Mutation ignoreResults {...opts} mutation={document}>
-            {/* @ts-expect-error */}
-            {(
-              mutate: MutationFunction<TData, TGraphQLVariables>,
-              { data, ...r }: MutationResult<TData>
-            ) => {
+            {(mutate, { data, ...r }) => {
               // the HOC's historically hoisted the data from the execution result
               // up onto the result since it was passed as a nested prop
               // we massage the Mutation component's shape here to replicate that
diff --git src/react/hooks/internal/useDeepMemo.ts src/react/hooks/internal/useDeepMemo.ts
index 916e23a746d..7faf0c6d43d 100644
--- src/react/hooks/internal/useDeepMemo.ts
+++ src/react/hooks/internal/useDeepMemo.ts
@@ -6,7 +6,7 @@ export function useDeepMemo<TValue>(
   memoFn: () => TValue,
   deps: DependencyList
 ) {
-  const ref = React.useRef<{ deps: DependencyList; value: TValue }>();
+  const ref = React.useRef<{ deps: DependencyList; value: TValue }>(void 0);
 
   if (!ref.current || !equal(ref.current.deps, deps)) {
     ref.current = { value: memoFn(), deps };
diff --git src/react/hooks/useLazyQuery.ts src/react/hooks/useLazyQuery.ts
index 671c23b9f86..e22b13fb0d4 100644
--- src/react/hooks/useLazyQuery.ts
+++ src/react/hooks/useLazyQuery.ts
@@ -82,11 +82,12 @@ export function useLazyQuery<
   options?: LazyQueryHookOptions<NoInfer<TData>, NoInfer<TVariables>>
 ): LazyQueryResultTuple<TData, TVariables> {
   const execOptionsRef =
-    React.useRef<Partial<LazyQueryHookExecOptions<TData, TVariables>>>();
-  const optionsRef = React.useRef<LazyQueryHookOptions<TData, TVariables>>();
+    React.useRef<Partial<LazyQueryHookExecOptions<TData, TVariables>>>(void 0);
+  const optionsRef =
+    React.useRef<LazyQueryHookOptions<TData, TVariables>>(void 0);
   const queryRef = React.useRef<
     DocumentNode | TypedDocumentNode<TData, TVariables>
-  >();
+  >(void 0);
   const merged = mergeOptions(options, execOptionsRef.current || {});
   const document = merged?.query ?? query;
 
diff --git src/testing/internal/rtl/renderHookAsync.tsx src/testing/internal/rtl/renderHookAsync.tsx
index fe411124357..77b998c8a78 100644
--- src/testing/internal/rtl/renderHookAsync.tsx
+++ src/testing/internal/rtl/renderHookAsync.tsx
@@ -31,6 +31,7 @@ export async function renderHookAsync<
 ): Promise<RenderHookResult<Result, Props>> {
   const { initialProps, ...renderOptions } = options;
 
+  // @ts-expect-error
   if (renderOptions.legacyRoot && typeof ReactDOM.render !== "function") {
     const error = new Error(
       "`legacyRoot: true` is not supported in this version of React. " +
diff --git src/utilities/index.ts src/utilities/index.ts
index 300cafb0d56..f4e7705deb6 100644
--- src/utilities/index.ts
+++ src/utilities/index.ts
@@ -139,6 +139,7 @@ export type { OnlyRequiredProperties } from "./types/OnlyRequiredProperties.js";
 export type { Prettify } from "./types/Prettify.js";
 export type { UnionToIntersection } from "./types/UnionToIntersection.js";
 export type { NoInfer } from "./types/NoInfer.js";
+export type { RemoveIndexSignature } from "./types/RemoveIndexSignature.js";
 
 export {
   AutoCleanedStrongCache,
diff --git a/src/utilities/types/RemoveIndexSignature.ts b/src/utilities/types/RemoveIndexSignature.ts
new file mode 100644
index 00000000000..4aad90687d9
--- /dev/null
+++ src/utilities/types/RemoveIndexSignature.ts
@@ -0,0 +1,6 @@
+export type RemoveIndexSignature<T> = {
+  [K in keyof T as string extends K ? never
+  : number extends K ? never
+  : symbol extends K ? never
+  : K]: T[K];
+};

Description

This PR introduces several changes and improvements to the Apollo Client codebase, primarily focusing on type definitions, testing configurations, and some minor bug fixes. The changes aim to enhance type safety, improve test coverage, and address some edge cases in data handling.

Changes

Changes

  1. API Reports:

    • Updated various API reports with new type definitions and changes to existing types.
  2. Jest Configuration:

    • Modified the Jest configuration to better handle different React versions in testing.
  3. Package Updates:

    • Updated several dependencies, including React and testing libraries.
  4. Type Improvements:

    • Enhanced ContainsFragmentsRefs type to prevent infinite recursion.
    • Improved Unmasked type to better handle tuple types.
    • Added RemoveIndexSignature type utility.
  5. Testing:

    • Added new tests for edge cases in data masking.
    • Updated some existing tests to accommodate new type definitions.
  6. Documentation:

    • Added new assets for VSCode extension documentation.
  7. Changelog:

    • Updated CHANGELOG.md with entries for version 3.12.3.
  8. Roadmap:

    • Updated ROADMAP.md with latest plans and timelines.
sequenceDiagram
    participant Dev as Developer
    participant CI as CI/CD Pipeline
    participant Repo as GitHub Repository

    Dev->>Repo: Push changes
    Repo->>CI: Trigger build
    CI->>CI: Run tests with updated Jest config
    CI->>CI: Generate new API reports
    CI->>CI: Update size limits
    CI->>Repo: Update documentation
    Repo->>Dev: Merge PR
    Dev->>Repo: Update CHANGELOG and ROADMAP
Loading

Possible Issues

  • The changes to type definitions, especially in data masking, might potentially break existing code that relies on the previous behavior.

Security Hotspots

None identified.

@tackley tackley merged commit 809aca9 into master Dec 18, 2024
9 checks passed
@tackley tackley deleted the renovate/all-minor-patch branch December 18, 2024 09:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dependencies Pull requests that update a dependency file puLL-Merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant